查看原文
其他

京东ES支持ZSTD压缩算法上线了:高性能,低成本

京东科技 杨松柏 京东技术
2024-08-24


Tech

导读

京东ES支持ZSTD压缩算法上线了,这是一种高性能、低成本的压缩算法,能够提高数据存储和传输的效率,同时降低存储和带宽成本。ZSTD算法是一种快速压缩算法,可提供比其他压缩算法更高的压缩比和更快的压缩速度。这意味着,京东ES用户可以更高效地存储和传输数据,同时节省存储和带宽成本。此外,ZSTD算法还具有更好的可扩展性和鲁棒性,可满足大规模分布式系统的需求。因此,京东ES支持ZSTD压缩算法上线,将为用户带来更高的性能、更低的成本和更好的体验。




01 前言

在今年的敏捷团队建设中,我通过Suite执行器实现了一键自动化单元测试。Juint除了Suite执行器还有哪些执行器呢?由此我的Runner探索之旅开始了!

在2022年10月份《ElasticSearch降本增效常见的方法》一文中曾提到过zstd压缩算法[1],一步一个脚印,我们终于在京东ES上线支持了zstd;我觉得促使目标完成主要以下几点原因:

1.Elastic官方原因:zstd压缩算法没有在Elastic官方的开发计划中;Elastic的licenes变更,很多功能使用受限

2.ES产品竞争力:提升京东ES产品在业界的竞争力,两大云友商和其他大厂都在陆续支持,在对外比拼的时候,我们需要提升我们这方面的能力

3.信创大背景:我们需要对开源组件有更好的自主管控和建设能力

4.京东零售ES与云ES产品融合:有更好的机会去打磨我们的ES内核

5.降本增效:ztsd压缩算法,能够在降低存储成本的前提下,保证性能几乎不受损,写入性能还有所提升



02   

测试结果

  

理解,首先 MCube 会依据模板缓存状态判断是否需要网络获取最新模板,当获取到模板后进行模板加载,加载阶段会将产物转换为视图树的结构,转换完成后将通过表达式引擎解析表达式并取得正确的值,通过事件解析引擎解析用户自定义事件并完成事件的绑定,完成解析赋值以及事件绑定后进行视图的渲染,最终将目标页面展示到屏幕。

测试集群配置:4c8g; 3个数据节点;

测试索引设置:3主分片1副本

测试数据mapping: keyword字段14个,geo_point字段3个,integer字段2个,text字段1个,date字段:2个,ip类型字段1个,boolean字段1个

在考虑到读写性能和压缩比均衡的情况下,我们推荐使用jd_zstd(压缩等级3):

  • jd_zstd(压缩等级3)写入性能相对于best_compression提升38.46%,相对于lz提升5.88%
  • jd_zstd(压缩等级3)存储相对于lz4节省24%,与best_compression基本持平,单位写的gb实际是要比best_compression的存储量小。

下表为es6.8.23版本,在cpu压测到100%时,不通压缩算法下ES的bulk、termquery、rangequery、matchquery等TPS以及压缩比测试结果:

注意⚠️:测试数据仅供参考,实际情况与用户数据有关


03   适用场景 

 



理解,首先 MCube 会依据模板缓存状态判断是否需要网络获取最新模板,当获取到模板后进行模板加载,加载阶段会将产物转换为视图树的结构,转换完成后将通过表达式引擎解析表达式并取得正确的值,通过事件解析引擎解析用户自定义事件并完成事件的绑定,完成解析赋值以及事件绑定后进行视图的渲染,最终将目标页面展示到屏幕。    1.位图原理
写多读少的场景,比如日志和监控场景。


04   使用方法 

 



理解,首先 MCube 会依据模板缓存状态判断是否需要网络获取最新模板,当获取到模板后进行模板加载,加载阶段会将产物转换为视图树的结构,转换完成后将通过表达式引擎解析表达式并取得正确的值,通过事件解析引擎解析用户自定义事件并完成事件的绑定,完成解析赋值以及事件绑定后进行视图的渲染,最终将目标页面展示到屏幕。    1.位图原理

云上ES等待上线后,可以进行申请

目前我们暂时只在内部泰山零售ES上线,支持7.X和6.8.23版本;后续会在云舰ES和公有云ES上线,由于licenes的限制,我们将只推出6.8.23版本。

Q1: 如何申请?

A1: 内部用户:之前在泰山平台申请的杰斯ES,如果使用的是7.X和6.8.23,可以选择版本升级到最新版本。新建集群,直接提工单申请

Q2 ztsd如何使用?

A2: 我们在ES中支持两种zstd压缩等级,用户可以根据自己的业务和数据特性选择合适的压缩等级;ES创建索引时指定index.codec:jd_zstd(压缩等级为3)或者jd_zstd_6(压缩等级为6)即可,其余没有其他任何特殊之处。

注意⚠️:index.codec的压缩算法不支持动态修改,必须创建索引时设定好。

# 创建索引zstdtest 压缩等级为 3PUT zstdtest{ "settings": { "index": { "codec": "jd_zstd" } }}
# 创建索引zstdtest_6 压缩等级为 3PUT zstdtest_6{ "settings": { "index": { "codec": "jd_zstd_6" } }}



05   技术实现 

 



理解,首先 MCube 会依据模板缓存状态判断是否需要网络获取最新模板,当获取到模板后进行模板加载,加载阶段会将产物转换为视图树的结构,转换完成后将通过表达式引擎解析表达式并取得正确的值,通过事件解析引擎解析用户自定义事件并完成事件的绑定,完成解析赋值以及事件绑定后进行视图的渲染,最终将目标页面展示到屏幕。    1.位图原理
首先我们介绍下ES与Lucene的关系;如下图所示,在集群层面:一个ES集群由多个节点组成。数据层面:1个索引是由多个分片组成的,一个分片可以看是一个Lucene实例;一个分片包含多个segement,一个segement即一组数据的最小单元,包含很多的数据文件。

1.Lucene文件
lucene[2]的数据文件主要由以下文件组成:

上述的文件大致可以分为以下几类:

  • 行存相关文件:主要包括原文存储文件.fdt和原文索引文件.fdx。用户写入的原始数据都被存储于.fdt,占比是最大的,Lucene在原文存储上支持LZ4和ZIP(best_compression)压缩。在写入数据时,ES把doc原始数据的整个json结构体当做一个string,存储为_source字段,因此原文存储文件.fdt中_source字段占比最大;部分场景为了节省磁盘存储,直接将该字段关闭,数据查询时仍可通过ES的docvalue_fields获取所有字段的值;
"_source": { "enabled": false }
注意⚠️:关闭_source后, update, update_by_query, reindex等功能无法正常使用,因此有update等需求的索引不能关闭_source.
  • 列存相关文件:.dvd文件,常用于OLAP分析,ES使用列存来支持sorting, aggregations和scripts功能。不同文档Document中的同一列(Field)数据相邻存放,加速列聚合分析性查询。相邻每列类型相同,在存储的时候可以进行统一性的编码优化,提高压缩率,减少存储磁盘空间的占用。ES中字段使用doc_values字为true,即为开启列存储。
  • 索引相关文件:主要文件包括字典数据文件.tim和倒排索引.doc文件。ES依靠分词器产生倒排索引,从而具备强大的全文检索能力。索引配置分词器后,将从摄入文档数据中提取分词信息并存储于.tim文件。同一列的分词信息相邻存放,按块组织;.doc文件也被称为"倒排拉链表",记录每一个词项所关联的文档id列表,实现词项到文档的快速倒排查找。倒排索引也会进行压缩,其压缩算法主要有Frame Of Reference、Roaring Bitmap和fst等。
  • 向量数据文件:矢量索引tvx和矢量数据.tvd文件,支持以图搜图,和音频的查找等。通过对摄入实体进行矢量化,然后使用向量搜索算法进行检索。相关向量搜索算法有HNSW[3],近似向量搜索knn[4];elastic公司在今年5月份左右推出用于人工智能的 Elasticsearch 相关性引擎ESRE[5]。
zstd主要压缩为行存储相关文件.fdm、.fdt 和.fdx;如下代码块为压缩文件对比,可以看出在不同的压缩算法中,这几个文件的大小是不同的。
# 为了节省篇幅部分文件省略 ## lz4压缩算法索引testlz4 0 号分片total 2.4G-rw-r--r-- 1 admin admin 1.2K Nov 16 16:19 _32.fdm-rw-r--r-- 1 admin admin 1.3G Nov 16 16:19 _32.fdt-rw-r--r-- 1 admin admin 76K Nov 16 16:19 _32.fdx-rw-r--r-- 1 admin admin 85M Nov 16 16:21 _32.kdd-rw-r--r-- 1 admin admin 149M Nov 16 16:21 _32_Lucene80_0.dvd.........................................-rw-r--r-- 1 admin admin 401 Nov 16 16:21 segments_b-rw-r--r-- 1 admin admin 0 Oct 16 16:05 write.lock
## best_compression压缩算法索引 testbestcompression 0 号分片total 1.9G-rw-r--r-- 1 admin admin 287 Nov 16 17:01 _2b.fdm-rw-r--r-- 1 admin admin 781M Nov 16 17:01 _2b.fdt-rw-r--r-- 1 admin admin 17K Nov 16 17:01 _2b.fdx-rw-r--r-- 1 admin admin 85M Nov 16 17:03 _2b.kdd-rw-r--r-- 1 admin admin 148M Nov 16 17:03 _2b_Lucene80_0.dvd.........................................-rw-r--r-- 1 admin admin 401 Nov 16 17:03 segments_a-rw-r--r-- 1 admin admin 0 Oct 16 16:27 write.lock
## zstd压缩等级为3 索引testzstd3 0 号分片total 1.9G-rw-r--r-- 1 admin admin 286 Nov 16 17:26 _8e.fdm-rw-r--r-- 1 admin admin 758M Nov 16 17:26 _8e.fdt-rw-r--r-- 1 admin admin 15K Nov 16 17:26 _8e.fdx-rw-r--r-- 1 admin admin 84M Nov 16 17:29 _8e.kdd-rw-r--r-- 1 admin admin 148M Nov 16 17:29 _8e_Lucene80_0.dvd-rw-r--r-- 1 admin admin 3.5K Nov 16 17:29 .........................................-rw-r--r-- 1 admin admin 402 Nov 16 17:29 segments_9-rw-r--r-- 1 admin admin 0 Nov 15 16:50 write.lock
## zstd压缩等级为6 索引testzstd6 0 号分片total 1.9G-rw-r--r-- 1 admin admin 286 Nov 16 16:56 _29.fdm-rw-r--r-- 1 admin admin 742M Nov 16 16:56 _29.fdt-rw-r--r-- 1 admin admin 9.8K Nov 16 16:56 _29.fdx-rw-r--r-- 1 admin admin 86M Nov 16 16:58 _29.kdd-rw-r--r-- 1 admin admin 148M Nov 16 16:58 _29_Lucene80_0.dvd.........................................-rw-r--r-- 1 admin admin 412 Nov 16 16:58 segments_a-rw-r--r-- 1 admin admin 0 Oct 16 16:04 write.lock
## zstd压缩等级为9 索引testzstd9 0 号分片total 1.9G-rw-r--r-- 1 admin admin 286 Nov 16 17:21 _gp.fdm-rw-r--r-- 1 admin admin 738M Nov 16 17:21 _gp.fdt-rw-r--r-- 1 admin admin 13K Nov 16 17:21 _gp.fdx-rw-r--r-- 1 admin admin 85M Nov 16 17:23 _gp.kdd-rw-r--r-- 1 admin admin 149M Nov 16 17:23 _gp_Lucene80_0.dvd.........................................-rw-r--r-- 1 admin admin 402 Nov 16 17:23 segments_8-rw-r--r-- 1 admin admin 0 Nov 15 16:50 write.lock
2.ES侧实现
理论上来说index.codec支持的压缩算法最好下沉到lucene代码中,目前我们并没有维护lucene代码,因此我们直接ES侧面代码实现。zstd[1]算法是基于C++实现,而ES是基于java编写,因此借助开源的力量,引入zstd-jni来实现zstd压缩能力。
# zstd_jni版本 1.5.5-1api "com.github.luben:zstd-jni:${versions.zstd_jni}"

在ES代码中编写自定义的index.codec;扩展CompressionMode压缩模式,自定义实现ZstdCompressor压缩和ZstdDecompressor解压缩方法,可以在这设定zstd的压缩等级以及控制读写数据块大小;最后通过java的spl机制实现加载我们自定义的压缩算法实现类

在server/src/main/resources/META-INF/services/org.apache.lucene.codecs.Codec文件中定义如下。
org.elasticsearch.index.codec.custom.ZstdCodec
注意⚠️:由于ES节点启动的时候,有security检查机制,因此我们需要在server/src/main/resources/org/elasticsearch/bootstrap/security.policy文件中添加代码权限授权策略
grant codeBase "${codebase.zstd-jni}" { permission java.lang.RuntimePermission "loadLibrary.*"; permission java.lang.RuntimePermission "libzstd.*";};



06   参考文献 

 



理解,首先 MCube 会依据模板缓存状态判断是否需要网络获取最新模板,当获取到模板后进行模板加载,加载阶段会将产物转换为视图树的结构,转换完成后将通过表达式引擎解析表达式并取得正确的值,通过事件解析引擎解析用户自定义事件并完成事件的绑定,完成解析赋值以及事件绑定后进行视图的渲染,最终将目标页面展示到屏幕。    1.位图原理

[1] https://github.com/facebook/zstd
[2] https://lucene.apache.org/core/8_11_2/core/org/apache/lucene/codecs/lucene87/package-summary.html#package.description
[3] Y. Malkov, D. Yashunin,Efficient and robust approximate nearest neighbor search using Hierarchical Navigable Small World graphs(2016), IEEE Transactions on Pattern Analysis and Machine Intelligence
[4]https://www.elastic.co/guide/en/elasticsearch/reference/current/knn-search.html#approximate-knn
[5] https://mp.weixin.qq.com/s/awxgy9pSgv0lVPTfvzfxBw
[6] https://mp.weixin.qq.com/
s/dmJwEpl6CWtv-MLdvR7g



推荐阅读
大文件上传实践分享
一次因PageHelper引起的多线程复用问题的排查和解决哎呀,当时怎么没有想到
得嘞,分页插件PageHelper返回记录总数total竟然出错了!


求分享

求点赞

求在看

打造SAAS化服务的会员徽章体系,可以作为标准的产品化方案统一对外输出。结合现有平台的通用能力,实现会员行为全路径覆盖,并能结合企业自身业务特点,规划相应的会员精准营销活动,提升会员忠诚度和业务的持续增长。底层能力:维护用户基础数据、行为数据建模、用户画像分析、精准营销策略的制定

▪功能支撑:会员成长体系、等级计算策略、权益体系、营销底层能力支持

▪用户活跃:会员关怀、用户触达、活跃活动、业务线交叉获客、拉新促

继续滑动看下一个
京东技术
向上滑动看下一个

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存